package com.miranteinfo.seam.hibernate.envers.listener;

import java.lang.reflect.Field;

import org.hibernate.cfg.Configuration;
import org.hibernate.envers.revisioninfo.DefaultRevisionInfoGenerator;
import org.hibernate.envers.synchronization.AuditSyncManager;

/**
 * Supports to envers revision entity listener configuration
 * 
 * @author lucas lins
 *
 */
public class AuditEventListener extends org.hibernate.envers.event.AuditEventListener{

	// ATTRIBUTES ***************************
	
	private static final long serialVersionUID = 1L;

	// PUBLIC METHODS ***********************
	
	@Override
	public void initialize(Configuration cfg) {
		super.initialize(cfg);
		if(cfg.getProperties().containsKey("org.hibernate.envers.revision_listener")){
			setRevisionEntityListener(getVerCfg().getSyncManager(), (String)cfg.getProperties().get("org.hibernate.envers.revision_listener"));
		}
	}
	
	// PRIVATE METHODS ***********************
	
	private void setRevisionEntityListener(AuditSyncManager syncManager, String listenerClass){
		try{
			Field listenerField = DefaultRevisionInfoGenerator.class.getDeclaredField("listener");
			listenerField.setAccessible(true);
			
			DefaultRevisionInfoGenerator revisionInfoGenerator = getRvisionInfoGenerator(syncManager);
			
			if(listenerField.get(revisionInfoGenerator) == null){
				listenerField.set(revisionInfoGenerator, Class.forName(listenerClass).newInstance());
			}
		}catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	private DefaultRevisionInfoGenerator getRvisionInfoGenerator(AuditSyncManager auditSyncManager) throws Exception{
		Field field = AuditSyncManager.class.getDeclaredField("revisionInfoGenerator");
		field.setAccessible(true);
		return (DefaultRevisionInfoGenerator)field.get(auditSyncManager);
	}
}
